package Test;

import static org.junit.Assert.*;

import org.junit.Test;

import LatentTicTacToe.Data.Board;
import LatentTicTacToe.Data.Move;

public class BoardTest {

	@Test
	public void makeMoveAndReverseMoveTest() {
		
		Board board = new Board(3, 3, (byte)1);
		
		board.makeMove(new Move((byte)0, (byte)0), (byte)1);
		board.makeMove(new Move((byte)2, (byte)2), (byte)2);
		board.makeMove(new Move((byte)1, (byte)0), (byte)1);
		
		board.reverseMove();
		
		assertEquals("0.00", board.id);
		
		byte[][] expectedLatentBoard = new byte[][]{{1, 0, 0}, {0, 0, 0}, {0, 0, 0}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedLatentBoard[j][i], board.latentSituation[j][i]);
			}
		}
		
		byte[][] expectedRealBoard = new byte[][]{{1, 0, 0}, {0, 0, 0}, {0, 0, 2}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedRealBoard[j][i], board.realSituation[j][i]);
			}
		}
		
		assertEquals(new Move((byte)2, (byte)2), board.history.pop());
	}
	
	@Test
	public void makeMoveAndReverseMoveTestOne() {
		
		Board board = new Board(3, 3, (byte)1);
		
		board.makeMove(new Move((byte)0, (byte)0), (byte)1);
		board.makeMove(new Move((byte)2, (byte)2), (byte)2);
		board.makeMove(new Move((byte)1, (byte)0), (byte)1);
		
		board.reverseMove();
		
		board.makeMove(new Move((byte)1, (byte)1), (byte)1);
		
		assertEquals("0.00.22", board.id);
		
		byte[][] expectedLatentBoard = new byte[][]{{1, 0, 0}, {0, 0, 0}, {0, 0, 2}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedLatentBoard[j][i], board.latentSituation[j][i]);
			}
		}
		
		byte[][] expectedRealBoard = new byte[][]{{1, 0, 0}, {0, 1, 0}, {0, 0, 2}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedRealBoard[j][i], board.realSituation[j][i]);
			}
		}
		
		
		assertEquals(new Move((byte)1, (byte)1), board.history.pop());
	}	
	
	@Test
	public void makeMoveTestWithInvalidMove() {
		
		Board board = new Board(3, 3, (byte)1);
		
		board.makeMove(new Move((byte)0, (byte)0), (byte)1);
		board.makeMove(new Move((byte)2, (byte)2), (byte)2);
		board.makeMove(new Move((byte)2, (byte)2), (byte)1);
		
		assertEquals("0.00.22.22", board.id);
		
		byte[][] expectedLatentBoard = new byte[][]{{1, 0, 0}, {0, 0, 0}, {0, 0, 2}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedLatentBoard[j][i], board.latentSituation[j][i]);
			}
		}
		
		byte[][] expectedRealBoard = new byte[][]{{1, 0, 0}, {0, 0, 0}, {0, 0, 2}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedRealBoard[j][i], board.realSituation[j][i]);
			}
		}
	}
	
	@Test
	public void makeMoveAndReverseMoveTestWithInvalidMove() {
		
		Board board = new Board(3, 3, (byte)1);
		
		board.makeMove(new Move((byte)0, (byte)0), (byte)1);
		board.makeMove(new Move((byte)2, (byte)2), (byte)2);
		board.makeMove(new Move((byte)2, (byte)2), (byte)1);
		
		board.reverseMove();
		
		assertEquals("0.00", board.id);
		
		byte[][] expectedLatentBoard = new byte[][]{{1, 0, 0}, {0, 0, 0}, {0, 0, 0}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedLatentBoard[j][i], board.latentSituation[j][i]);
			}
		}
		
		byte[][] expectedRealBoard = new byte[][]{{1, 0, 0}, {0, 0, 0}, {0, 0, 2}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedRealBoard[j][i], board.realSituation[j][i]);
			}
		}
		
		assertEquals(new Move((byte)2, (byte)2), board.history.pop());
		assertEquals(new Move((byte)0, (byte)0), board.history.pop());
	}
	
	@Test
	public void makeMoveAndReverseMoveTestOnFirstMove() {
		
		Board board = new Board(3, 3, (byte)1);
		
		board.makeMove(new Move((byte)0, (byte)0), (byte)1);
		
		board.reverseMove();
		
		assertEquals("", board.id);
		
		byte[][] expectedLatentBoard = new byte[][]{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedLatentBoard[j][i], board.latentSituation[j][i]);
			}
		}
		
		byte[][] expectedRealBoard = new byte[][]{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedRealBoard[j][i], board.realSituation[j][i]);
			}
		}
		
	}
	
	@Test
	public void makeMoveAndReverseMoveTestOnSecondtMove() {
		
		Board board = new Board(3, 3, (byte)1);
		
		board.makeMove(new Move((byte)0, (byte)0), (byte)1);
		board.makeMove(new Move((byte)2, (byte)2), (byte)2);
		
		board.reverseMove();
		
		assertEquals("0", board.id);
		
		byte[][] expectedLatentBoard = new byte[][]{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedLatentBoard[j][i], board.latentSituation[j][i]);
			}
		}
		
		byte[][] expectedRealBoard = new byte[][]{{1, 0, 0}, {0, 0, 0}, {0, 0, 0}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedRealBoard[j][i], board.realSituation[j][i]);
			}
		}
	}
	
	@Test
	public void makeMoveTestAfterInvalidMove() {
		
		Board board = new Board(3, 3, (byte)1);
		
		board.makeMove(new Move((byte)0, (byte)0), (byte)1);
		board.makeMove(new Move((byte)2, (byte)2), (byte)2);
		board.makeMove(new Move((byte)2, (byte)2), (byte)1);
		board.makeMove(new Move((byte)1, (byte)1), (byte)1);
		
		assertEquals("0.00.22", board.id);
		
		byte[][] expectedLatentBoard = new byte[][]{{1, 0, 0}, {0, 0, 0}, {0, 0, 2}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedLatentBoard[j][i], board.latentSituation[j][i]);
			}
		}
		
		byte[][] expectedRealBoard = new byte[][]{{1, 0, 0}, {0, 1, 0}, {0, 0, 2}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedRealBoard[j][i], board.realSituation[j][i]);
			}
		}
		
		assertEquals(new Move((byte)1, (byte)1), board.history.pop());
		assertEquals(new Move((byte)2, (byte)2), board.history.pop());
		assertEquals(new Move((byte)0, (byte)0), board.history.pop());
		
			
	}
	
	@Test
	public void makeMoveAndReverseMoveTestAfterInvalidMove() {
		
		Board board = new Board(3, 3, (byte)1);
		
		board.makeMove(new Move((byte)0, (byte)0), (byte)1);
		board.makeMove(new Move((byte)2, (byte)2), (byte)2);
		board.makeMove(new Move((byte)2, (byte)2), (byte)1);
		board.makeMove(new Move((byte)1, (byte)1), (byte)1);
		
		board.reverseMove();
		
		assertEquals("0.00", board.id);
		
		byte[][] expectedLatentBoard = new byte[][]{{1, 0, 0}, {0, 0, 0}, {0, 0, 0}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedLatentBoard[j][i], board.latentSituation[j][i]);
			}
		}
		
		byte[][] expectedRealBoard = new byte[][]{{1, 0, 0}, {0, 0, 0}, {0, 0, 2}};
		
		for (int i = 0; i < expectedLatentBoard.length; i++) {
			for (int j = 0; j < expectedLatentBoard.length; j++) {
				assertEquals(expectedRealBoard[j][i], board.realSituation[j][i]);
			}
		}
		
		assertEquals(new Move((byte)2, (byte)2), board.history.pop());
		assertEquals(new Move((byte)0, (byte)0), board.history.pop());
		
			
	}

}
